package club.gskj.gulimall.order.service.impl;

import club.gskj.gulimall.order.entity.OrderEntity;
import club.gskj.gulimall.order.entity.OrderReturnReasonEntity;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import club.gskj.common.utils.PageUtils;
import club.gskj.common.utils.Query;

import club.gskj.gulimall.order.dao.OrderItemDao;
import club.gskj.gulimall.order.entity.OrderItemEntity;
import club.gskj.gulimall.order.service.OrderItemService;


/**
 * 使用@RabbitListener 监听多个队列的消息接受
 */
//@RabbitListener(queues = {"hello.java.Queue"})
@Slf4j
@Service("omsOrderItemService")
public class OrderItemServiceImpl extends ServiceImpl<OrderItemDao, OrderItemEntity> implements OrderItemService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderItemEntity> page = this.page(
                new Query<OrderItemEntity>().getPage(params),
                new QueryWrapper<OrderItemEntity>()
        );
        return new PageUtils(page);
    }

    /**
     * 接受 OrderReturnReasonEntity
     *
     * @RabbitListener queues[]: 指定要监听的队列
     * messahe 的类型为 org.springframework.amqp.core.Message
     * <p>
     * 方法参数可以直接写 Message类型
     * 1. Message memssage 原始的消息信息
     * 2. T<发送的消息类型>  当前发送给信息类型为：OrderReturnReasonEntity order,
     * 3. Channel channel 当前接受消息的通道
     * <p>
     * Queue: 可以有很多人来监听，只要接收到信息，队列就会删除该消息。而且只能有一个能收到次信息。
     * <p>
     * 场景：
     * 1. 启动多个order服务,同一个消息，只能由一个客户端接受
     * 2. 只有当一个消息处理完(即业务方法执行完)，才会处理下一个消息
     */
//    @RabbitListener(queues = {"hello.java.Queue"})
//    @RabbitHandler
    public void acceptMessage(Message memssage, OrderReturnReasonEntity order, Channel channel) {

        // 消息体
        byte[] body = memssage.getBody();

        // 消息头
        MessageProperties messageProperties = memssage.getMessageProperties();
//        接受的消息内容 (Body:'{"id":1,"name":"test-connor","sort":1,"status":1,"createTime":1616838389645}' MessageProperties [headers={__TypeId__=club.gskj.gulimall.order.entity.OrderReturnReasonEntity}, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=hello.java.exchange, receivedRoutingKey=hello.java, deliveryTag=1, consumerTag=amq.ctag-LPRxGISkDjFx1LchHHIasw, consumerQueue=hello.java.Queue])内容 :OrderReturnReasonEntity(id=1, name=test-connor, sort=1, status=1, createTime=Sat Mar 27 17:46:29 GMT+08:00 2021)
//        log.info("接受的消息内容 {}", memssage + "内容 :" + order);

        // channel通道内 按顺序自增的 数字
        long deliveryTag = memssage.getMessageProperties().getDeliveryTag();
        log.info("自增数字 {}", deliveryTag);

        // 签收消息,非批量签收,
        try {
            if (deliveryTag % 2 == 0) {
                // 签收
                channel.basicAck(deliveryTag, false);
                log.info("签收的消息 {}", deliveryTag);
            } else {
                // 拒绝签收
                //    void basicNack(long deliveryTag, boolean multiple 是否批量拒绝, boolean requeue 是否重新入队: true发回服务器重新入队,false 丢弃消息)
                channel.basicNack(deliveryTag, false, true);
                //     void basicReject(long deliveryTag, boolean requeue) throws IOException;
//                channel.basicReject();
                log.info("未签收的消息 {}", deliveryTag);
            }
        } catch (IOException e) {
            // 网络异常
            e.printStackTrace();
        }
        log.info("接受的消息内容 {}", order);
    }

    /**
     * @RabbitHandler 指定方法接受不同类型的消息内容
     * 接受Order信息
     */
//    @RabbitHandler
    public void acceptMessage(Message memssage, OrderEntity order, Channel channel) {
        log.info("接受的消息内容 {}", order);
    }
}
